package org.breathe.dynamic.thread.pool.core.thread;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.ttl.threadpool.TtlExecutors;
import lombok.Data;
import org.breathe.dynamic.thread.pool.core.reject.RejectHandlerGetter;
import org.breathe.thread.pool.common.constant.BreatheDtpConstant;
import org.breathe.thread.pool.common.entity.NotifyItem;
import org.breathe.thread.pool.common.enums.QueueTypeEnum;
import org.breathe.thread.pool.common.queue.MemorySafeLinkedBlockingQueue;

import java.util.List;
import java.util.concurrent.*;

/**
 * 优雅的创建一个线程池
 * @author: breathe
 * @createTime: 2025-04-11
 */
@Data
public class ThreadPoolBuilder {
    /**
     * 动态线程池的名字
     */
    private String threadPoolName = "breatheDynamicTp";

    /**
     * 核心线程数
     */
    private int corePoolSize = 1;

    /**
     * 最大线程数
     */
    private int maximumPoolSize = BreatheDtpConstant.AVAILABLE_PROCESSORS;

    /**
     * 非核心线程所能不活跃的最大时间
     */
    private long keepAliveTime = 30L;

    /**
     * 时间单位
     */
    private TimeUnit timeUnit = TimeUnit.SECONDS;

    /**
     * 阻塞队列
     */
    private BlockingQueue<Runnable> workQueue = new MemorySafeLinkedBlockingQueue<>(1024);

    /**
     * 拒绝策略
     */
    private RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.AbortPolicy();

    /**
     * 默认线程工厂
     */
    private ThreadFactory threadFactory = new NamedThreadFactory("breathe-dynamic-tp");

    /**
     * 如果允许核心线程超时
     */
    private boolean allowCoreThreadTimeOut = false;

    /**
     * 动态或者普通
     */
    private boolean dynamic = true;

    /**
     * 报警相关
     */
    private List<NotifyItem> notifyItems = NotifyItem.getDefaultNotifyItems();

    private ThreadPoolBuilder() {}
    public static ThreadPoolBuilder newBuilder() {
        return new ThreadPoolBuilder();
    }
    public ThreadPoolBuilder threadPoolName(String poolName) {
        this.threadPoolName = poolName;
        return this;
    }
    public ThreadPoolBuilder corePoolSize(int corePoolSize) {
        if (corePoolSize >= 0) {
            this.corePoolSize = corePoolSize;
        }
        return this;
    }
    public ThreadPoolBuilder maximumPoolSize(int maximumPoolSize) {
        if (maximumPoolSize > 0) {
            this.maximumPoolSize = maximumPoolSize;
        }
        return this;
    }
    public ThreadPoolBuilder keepAliveTime(long keepAliveTime) {
        if (keepAliveTime > 0) {
            this.keepAliveTime = keepAliveTime;
        }
        return this;
    }
    public ThreadPoolBuilder timeUnit(TimeUnit timeUnit) {
        if (timeUnit != null) {
            this.timeUnit = timeUnit;
        }
        return this;
    }

    /**
     * 创建阻塞队列
     */
    public ThreadPoolBuilder workQueue(String queueName, Integer capacity, Boolean fair) {
        if (StrUtil.isNotBlank(queueName)) {
            workQueue = QueueTypeEnum.buildBlockingQueue(queueName, capacity != null ? capacity : 1024, fair != null && fair);
        }
        return this;
    }

    /**
     * 拒绝策略
     */
    public ThreadPoolBuilder rejectedExecutionHandler(String rejectedName) {
        if (StrUtil.isNotBlank(rejectedName)) {
            rejectedExecutionHandler = RejectHandlerGetter.buildRejectedHandler(rejectedName);
        }
        return this;
    }

    /**
     * 线程工厂
     */
    public ThreadPoolBuilder threadFactory(String prefix) {
        if (StrUtil.isNotBlank(prefix)) {
            threadFactory = new NamedThreadFactory(prefix);
        }
        return this;
    }

    /**
     * 允许核心线程超时
     */
    public ThreadPoolBuilder allowCoreThreadTimeOut(boolean allowCoreThreadTimeOut) {
        this.allowCoreThreadTimeOut = allowCoreThreadTimeOut;
        return this;
    }

    /**
     * 是否动态
     */
    public ThreadPoolBuilder dynamic(boolean dynamic) {
        this.dynamic = dynamic;
        return this;
    }
    /**
     * 报警
     */
    public ThreadPoolBuilder notifyItems(List<NotifyItem> notifyItemList) {
        if (CollUtil.isNotEmpty(notifyItemList)) {
            notifyItems = notifyItemList;
        }
        return this;
    }
    /**
     * 根据dynamic来建造
     */
    public ThreadPoolExecutor build() {
        return dynamic ? buildBreatheDtpExecutor(this) : buildCommonExecutor(this);
    }

    /**
     * 建造一个动态的
     * @return
     */
    public BreatheDtpExecutor buildDynamic() {
        return buildBreatheDtpExecutor(this);
    }

    /**
     * 建造一个普通的
     */
    public ThreadPoolExecutor buildCommon() {
        return buildCommonExecutor(this);
    }

    /**
     * 建造线程池并且用ttl包装
     */
    public ExecutorService buildWithTtl() {
        return TtlExecutors.getTtlExecutorService(buildCommonExecutor(this));
    }

    /**
     * 建造动态线程池
     */
    private BreatheDtpExecutor buildBreatheDtpExecutor(ThreadPoolBuilder builder) {
        Assert.notNull(builder.threadPoolName, "The thread pool name must not be null");
        BreatheDtpExecutor executor = new BreatheDtpExecutor(
                builder.corePoolSize,
                builder.maximumPoolSize,
                builder.keepAliveTime,
                builder.timeUnit,
                builder.workQueue,
                builder.threadFactory,
                builder.rejectedExecutionHandler
        );
        executor.allowCoreThreadTimeOut(builder.allowCoreThreadTimeOut);
        executor.setThreadPoolName(builder.threadPoolName);
        executor.setNotifyItems(notifyItems);
        return executor;
    }

    /**
     * 建造普通线程池
     */
    private ThreadPoolExecutor buildCommonExecutor(ThreadPoolBuilder builder) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                builder.corePoolSize,
                builder.maximumPoolSize,
                builder.keepAliveTime,
                builder.timeUnit,
                builder.workQueue,
                builder.threadFactory,
                builder.rejectedExecutionHandler
        );
        executor.allowCoreThreadTimeOut(builder.allowCoreThreadTimeOut);
        return executor;
    }
}
